using System.Collections.Generic;
using Framework.StringSplit.Processors;

namespace Framework.StringSplit
{
    public class StringSplitFluent :
        BaseFluentConfigurable<StringSplitHandler, IStringSplitFluent, IStringSplitConfigurationFluent>,
        IStringSplitConfigurationFluent, IStringSplitFluent
    {
        //**************************************************************************************************************
        // Setup and Base implementation for Fluent interfaces
        //**************************************************************************************************************
        public StringSplitFluent()
        {
            Instance = new StringSplitHandler();

            Set(new[] {','});
        }

        /// <summary>
        /// Changes the context to fluent configuration mode.
        /// </summary>
        public override IStringSplitConfigurationFluent Config
        {
            get { return this; }
        }

        /// <summary>
        /// Ends the fluent configuation mode context and goes to excution mode.
        /// </summary>
        public override IStringSplitFluent End
        {
            get
            {
                //_.L("End");
                //_.Nv("Esc", Instance.Escape);
                //_.Nv("Seperator", Is.EmptyArray(Instance.SeperatorChar) ? "null" : Instance.SeperatorChar[0].ToString());
                //_.Nv("Count", Instance.Count);

                return this;
            }
        }

        //**************************************************************************************************************
        // Processing
        //**************************************************************************************************************

        public string[] Split<TProcessor>(string text) where TProcessor : IStringSplitProcessor<string[]>
        {
            var processor = ReflectUtil.CreateInstance<TProcessor>();

            return Instance.Split(processor, text);
        }

        public List<string> SplitAsList<TProcessor>(string text) where TProcessor : IStringSplitProcessor<List<string>>
        {
            var processor = ReflectUtil.CreateInstance<TProcessor>();

            return Instance.SplitAsList(processor, text);
        }

        public List<KeyValuePair<string, string>> SplitAsKeyValuePairList<TProcessor>(string text) where TProcessor : IStringSplitProcessor<List<KeyValuePair<string, string>>>
        {
            var processor = ReflectUtil.CreateInstance<TProcessor>();

            return Instance.SplitAsKeyValuePairList(processor, text);
        }

        //**************************************************************************************************************
        // Configuration
        //**************************************************************************************************************

        public IStringSplitConfigurationFluent Set(
            char[] seperator = null,
            StringSplitOptionsType options = StringSplitOptionsType.Default,
            char esc = '\\',
            char escInner = '~',
            int count = int.MaxValue,
            char[] seperatorInner = null)
        {
            SetSeperator(seperator);
            SetSeperatorInner(seperatorInner);
            SetOptions(options);
            SetEscape(esc);
            SetEscapeInner(escInner);

            return this;
        }

        public IStringSplitConfigurationFluent Set(
            string[] seperator = null,
            StringSplitOptionsType options = StringSplitOptionsType.Default,
            char esc = '\\',
            char escInner = '~',
            int count = int.MaxValue
            )
        {
            SetSeperator(seperator);
            SetOptions(options);
            SetEscape(esc);
            SetEscapeInner(escInner);

            return this;
        }

        public IStringSplitConfigurationFluent SetOptions(StringSplitOptionsType options)
        {
            if (options.EnumHas(StringSplitOptionsType.TrimWhitespace))
            {
                Instance.Trim = StringSplitTrimType.Trim;
            }
            else if (options.EnumHas(StringSplitOptionsType.TrimWhitespaceEnd))
            {
                Instance.Trim = StringSplitTrimType.TrimEnd;
            }
            else if (options.EnumHas(StringSplitOptionsType.TrimWhitespaceStart))
            {
                Instance.Trim = StringSplitTrimType.TrimStart;
            }
            else 
            {
                Instance.Trim = StringSplitTrimType.None;
            }

            Instance.RemoveEmptyEntries = options.EnumHas(StringSplitOptionsType.RemoveEmptyEntries);

            return this;
        }

        public IStringSplitConfigurationFluent SetSeperator(params char[] seperator)
        {
            if (seperator != null && seperator.Length == 0)
            {
                seperator = new[] { ',' };
            }
            Instance.SeperatorChar = seperator;

            return this;
        }

        public IStringSplitConfigurationFluent SetSeperatorInner(params char[] seperator)
        {
            Instance.SeperatorInnerChar = seperator;

            return this;
        }

        public IStringSplitConfigurationFluent SetSeperator(string[] seperator)
        {
            Instance.SeperatorString = seperator;

            return this;
        }

        public IStringSplitConfigurationFluent SetCount(int count)
        {
            Instance.Count = count;

            return this;
        }

        public IStringSplitConfigurationFluent SetEscape(char escape)
        {
            Instance.Escape = escape;

            return this;
        }

        public IStringSplitConfigurationFluent SetEscapeInner(char escape)
        {
            Instance.EscapeInner = escape;

            return this;
        }
    }
}